home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / INDENT3.ARJ / DOINDENT.C < prev    next >
C/C++ Source or Header  |  1992-08-04  |  17KB  |  552 lines

  1. #include "indent_globs.h"
  2.  
  3. struct parser_state match_state[STACK_SIZE];
  4. struct parser_state state_stack[STACK_SIZE];
  5.  
  6. extern int dec_ind;        /* current indentation for declarations */
  7. extern int di_stack[STACKS];    /* a stack of structure indentation levels */
  8. extern int flushed_nl;        /* used when buffering up comments to
  9.                  * remember that a newline was passed over */
  10. extern int force_nl;        /* when true, code must be broken */
  11. extern int hd_type;        /* used to store type of stmt for if (...),
  12.                  * for (...), etc */
  13. extern int scase;        /* set to true when we see a case, so we will
  14.                  * know what to do with the following colon */
  15. extern int sp_sw;        /* when true, we are in the expressin of
  16.                  * if(...), while(...), etc. */
  17. extern int squest;        /* when this is positive, we have seen a ?
  18.                  * without the matching : in a <c>?<s>:<s>
  19.                  * construct */
  20. extern int type_code;        /* the type of token, returned by lexi */
  21.  
  22. extern int last_else;        /* true iff last keyword was an else */
  23.  
  24. extern int is_procname;
  25.  
  26.  
  27. void switch_on(type_code)
  28.     int type_code;
  29. {
  30.     register int i;
  31.     register char *t_ptr;    /* used for copying tokens */
  32.  
  33.  
  34.     /*----------------------------------------------------*\
  35.      |   do switch on type of token scanned
  36.     \*----------------------------------------------------*/
  37.     switch (type_code) {    /* now, decide what to do with the token */
  38.  
  39.     case form_feed:    /* found a form feed in line */
  40.         ps.use_ff = true;    /* a form feed is treated much like a newline */
  41.         dump_line();
  42.         ps.want_blank = false;
  43.         break;
  44.  
  45.     case newline:
  46.         if (ps.last_token != comma || ps.p_l_follow > 0
  47.         || !ps.leave_comma || !break_comma || s_com != e_com) {
  48.         dump_line();
  49.         ps.want_blank = false;
  50.         }
  51.         ++line_no;        /* keep track of input line number */
  52.         break;
  53.  
  54.     case lparen:        /* got a '(' or '[' */
  55.         ++ps.p_l_follow;    /* count parens to make Healy happy */
  56.         if (ps.want_blank && *token != '[' &&
  57.         (ps.last_token != ident || proc_calls_space
  58.             || (ps.its_a_keyword && !ps.sizeof_keyword)))
  59.         *e_code++ = ' ';
  60.         if (ps.in_decl && !ps.block_init)
  61.         if (troff && !ps.dumped_decl_indent) {
  62.             ps.dumped_decl_indent = 1;
  63.             sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  64.             e_code += strlen(e_code);
  65.         } else {
  66.             while ((e_code - s_code) < dec_ind)
  67.             *e_code++ = ' ';
  68.             *e_code++ = token[0];
  69.         }
  70.         else
  71.         *e_code++ = token[0];
  72.         ps.paren_indents[ps.p_l_follow - 1] = e_code - s_code;
  73.         ps.want_blank = false;
  74.         if (ps.in_or_st && *token == '(') {
  75.  
  76.         /* this is a kluge to make sure that declarations will be
  77.          * aligned right if proc decl has an explicit type on it,
  78.          * i.e. "int a(x) {..." */
  79.         parse(semicolon);    /* I said this was a kluge... */
  80.         ps.in_or_st = false;    /* turn off flag for structure decl
  81.                      * or initialization */
  82.         }
  83.         if (ps.sizeof_keyword)
  84.         ps.sizeof_mask |= 1 << ps.p_l_follow;
  85.         break;
  86.  
  87.     case rparen:        /* got a ')' or ']' */
  88.         if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.sizeof_mask) {
  89.         ps.last_u_d = true;
  90.         ps.cast_mask &= (1 << ps.p_l_follow) - 1;
  91.         }
  92.         ps.sizeof_mask &= (1 << ps.p_l_follow) - 1;
  93.         if (--ps.p_l_follow < 0) {
  94.         ps.p_l_follow = 0;
  95.         diag(0, "Extra %c", *token);
  96.         }
  97.         if (e_code == s_code)    /* if the paren starts the line */
  98.         ps.paren_level = ps.p_l_follow;        /* then indent it */
  99.  
  100.         *e_code++ = token[0];
  101.         ps.want_blank = true;
  102.  
  103.         if (sp_sw && (ps.p_l_follow == 0)) {    /* check for end of if
  104.                              * (...), or some such */
  105.         sp_sw = false;
  106.         force_nl = true;/* must force newline after if */
  107.         ps.last_u_d = true;    /* inform lexi that a following
  108.                      * operator is unary */
  109.         ps.in_stmt = false;    /* dont use stmt continuation
  110.                      * indentation */
  111.  
  112.         parse(hd_type);    /* let parser worry about if, or whatever */
  113.         }
  114.         ps.search_brace = btype_2;    /* this should insure that constructs
  115.                      * such as main(){...} and int[]{...}
  116.                      * have their braces put in the right
  117.                      * place */
  118.         break;
  119.  
  120.     case unary_op:        /* this could be any unary operation */
  121.         if (ps.want_blank)
  122.         *e_code++ = ' ';
  123.  
  124.         if (troff && !ps.dumped_decl_indent && ps.in_decl) {
  125.         sprintf(e_code, "\\c\n.Du %dp+\200p \"%s\"\n", dec_ind * 7, token);
  126.         ps.dumped_decl_indent = 1;
  127.         e_code += strlen(e_code);
  128.         } else {
  129.         char *res = token;
  130.  
  131.         if (ps.in_decl && !ps.block_init) {    /* if this is a unary op
  132.                              * in a declaration, we
  133.                              * should indent this
  134.                              * token */
  135.             for (i = 0; token[i]; ++i);        /* find length of token */
  136.             while ((e_code - s_code) < (dec_ind - i))
  137.             *e_code++ = ' ';    /* pad it */
  138.         }
  139.         if (troff && token[0] == '-' && token[1] == '>')
  140.             res = "\\(->";
  141.         for (t_ptr = res; *t_ptr; ++t_ptr)
  142.             *e_code++ = *t_ptr;
  143.         }
  144.         ps.want_blank = false;
  145.         break;
  146.  
  147.     case binary_op:    /* any binary operation */
  148.     do_binary:
  149.         if (ps.want_blank)
  150.         *e_code++ = ' ';
  151.         {
  152.         char *res = token;
  153.  
  154.         if (troff)
  155.             switch (token[0]) {
  156.             case '<':
  157.                 if (token[1] == '=')
  158.                 res = "\\(<=";
  159.                 break;
  160.             case '>':
  161.                 if (token[1] == '=')
  162.                 res = "\\(>=";
  163.                 break;
  164.             case '!':
  165.                 if (token[1] == '=')
  166.                 res = "\\(!=";
  167.                 break;
  168.             case '|':
  169.                 if (token[1] == '|')
  170.                 res = "\\(br\\(br";
  171.                 else if (token[1] == 0)
  172.                 res = "\\(br";
  173.                 break;
  174.             case '-':
  175.                 if (token[1] == '>')
  176.                 res = "\\(->";
  177.             }
  178.         for (t_ptr = res; *t_ptr; ++t_ptr)
  179.             *e_code++ = *t_ptr;        /* move the operator */
  180.         }
  181.         ps.want_blank = true;
  182.         break;
  183.  
  184.     case postop:        /* got a trailing ++ or -- */
  185.         *e_code++ = token[0];
  186.         *e_code++ = token[1];
  187.         ps.want_blank = true;
  188.         break;
  189.  
  190.     case question:        /* got a ? */
  191.         squest++;        /* this will be used when a later colon
  192.                  * appears so we can distinguish the
  193.                  * <c>?<n>:<n> construct */
  194.         if (ps.want_blank)
  195.         *e_code++ = ' ';
  196.         *e_code++ = '?';
  197.         ps.want_blank = true;
  198.         break;
  199.  
  200.     case casestmt:        /* got word 'case' or 'default' */
  201.         scase = true;    /* so we can process the later colon properly */
  202.         goto copy_id;
  203.  
  204.     case colon:        /* got a ':' */
  205.         if (squest > 0) {    /* it is part of the <c>?<n>: <n> construct */
  206.         --squest;
  207.         if (ps.want_blank)
  208.             *e_code++ = ' ';
  209.         *e_code++ = ':';
  210.         ps.want_blank = true;
  211.         break;
  212.         }
  213.         if (ps.in_decl) {
  214.         *e_code++ = ':';
  215.         ps.want_blank = false;
  216.         break;
  217.         }
  218.         ps.in_stmt = false;    /* seeing a label does not imply we are in a
  219.                  * stmt */
  220.         for (t_ptr = s_code; *t_ptr; ++t_ptr)
  221.         *e_lab++ = *t_ptr;    /* turn everything so far into a
  222.                      * label */
  223.         e_code = s_code;
  224.         *e_lab++ = ':';
  225.         *e_lab++ = ' ';
  226.         *e_lab = '\0';
  227.  
  228.         force_nl = ps.pcase = scase;    /* ps.pcase will be used by
  229.                          * dump_line to decide how to
  230.                          * indent the label. force_nl
  231.                          * will force a case n: to be
  232.                          * on a line by itself */
  233.         scase = false;
  234.         ps.want_blank = false;
  235.         break;
  236.  
  237.     case semicolon:    /* got a ';' */
  238.         ps.in_or_st = false;/* we are not in an initialization or
  239.                  * structure declaration */
  240.         scase = false;    /* these will only need resetting in a error */
  241.         squest = 0;
  242.         if (ps.last_token == rparen)
  243.         ps.in_parameter_declaration = 0;
  244.         ps.cast_mask = 0;
  245.         ps.sizeof_mask = 0;
  246.         ps.block_init = 0;
  247.         ps.just_saw_decl--;
  248.  
  249.         if (ps.in_decl && s_code == e_code && !ps.block_init)
  250.         while ((e_code - s_code) < (dec_ind - 1))
  251.             *e_code++ = ' ';
  252.  
  253.         ps.in_decl = (ps.dec_nest > 0);    /* if we were in a first
  254.                          * level structure
  255.                          * declaration, we arent any
  256.                          * more */
  257.  
  258.         if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {
  259.  
  260.         /* This should be true iff there were unbalanced parens in
  261.          * the stmt.  It is a bit complicated, because the semicolon
  262.          * might be in a for stmt */
  263.         diag(1, "Unbalanced parens");
  264.         ps.p_l_follow = 0;
  265.         if (sp_sw) {    /* this is a check for a if, while, etc. with
  266.                  * unbalanced parens */
  267.             sp_sw = false;
  268.             parse(hd_type);    /* dont lose the if, or whatever */
  269.         }
  270.         }
  271.         *e_code++ = ';';
  272.         ps.want_blank = true;
  273.         ps.in_stmt = (ps.p_l_follow > 0);    /* we are no longer in the
  274.                          * middle of a stmt */
  275.  
  276.         if (!sp_sw) {    /* if not if for (;;) */
  277.         parse(semicolon);    /* let parser know about end of stmt */
  278.         force_nl = true;/* force newline after a end of stmt */
  279.         }
  280.         break;
  281.  
  282.     case lbrace:        /* got a 'lbrace' */
  283.         ps.in_stmt = false;    /* dont indent the {} */
  284.         if (!ps.block_init)
  285.         force_nl = true;/* force other stuff on same line as 'lbrace'
  286.                  * onto new line */
  287.  
  288.         if (s_code != e_code && !ps.block_init) {
  289.         if (!btype_2) {
  290.             dump_line();
  291.             ps.want_blank = false;
  292.         } else if (ps.in_parameter_declaration && !ps.in_or_st) {
  293.             ps.i_l_follow = 0;
  294.             dump_line();
  295.             ps.want_blank = false;
  296.         }
  297.         }
  298.         if (ps.in_parameter_declaration)
  299.         prefix_blankline_requested = 0;
  300.  
  301.         if (ps.p_l_follow > 0) {    /* check for preceding unbalanced
  302.                      * parens */
  303.         diag(1, "Unbalanced parens");
  304.         ps.p_l_follow = 0;
  305.         if (sp_sw) {    /* check for unclosed if, for, etc. */
  306.             sp_sw = false;
  307.             parse(hd_type);
  308.             ps.ind_level = ps.i_l_follow;
  309.         }
  310.         }
  311.         if (s_code == e_code)
  312.         ps.ind_stmt = false;    /* dont put extra indentation on line
  313.                      * with '{' */
  314.         if (ps.in_decl && ps.in_or_st) {    /* this is either a structure
  315.                          * declaration or an init */
  316.         di_stack[ps.dec_nest++] = dec_ind;
  317.         dec_ind = 0;
  318.         } else {
  319.         ps.decl_on_line = false;    /* we cant be in the middle
  320.                          * of a declaration, so dont
  321.                          * do special indentation of
  322.                          * comments */
  323.         ps.in_parameter_declaration = 0;
  324.         }
  325.         parse(lbrace);    /* let parser know about this */
  326.         if (ps.want_blank)    /* put a blank before '{' if '{' is not at
  327.                  * start of line */
  328.         *e_code++ = ' ';
  329.         ps.want_blank = false;
  330.         *e_code++ = '{';
  331.         ps.just_saw_decl = 0;
  332.         break;
  333.  
  334.     case rbrace:        /* got a '}' */
  335.         if (ps.p_l_follow) {/* check for unclosed if, for, else. */
  336.         diag(1, "Unbalanced parens");
  337.         ps.p_l_follow = 0;
  338.         sp_sw = false;
  339.         }
  340.         ps.just_saw_decl = 0;
  341.         if (s_code != e_code && !ps.block_init) {    /* '}' must be first on
  342.                              * line */
  343.         if (verbose)
  344.             diag(0, "Line broken");
  345.         dump_line();
  346.         }
  347.         *e_code++ = '}';
  348.         ps.want_blank = true;
  349.         ps.in_stmt = ps.ind_stmt = false;
  350.         if (ps.dec_nest > 0) {    /* we are in multi-level structure
  351.                      * declaration */
  352.         dec_ind = di_stack[--ps.dec_nest];
  353.         if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
  354.             ps.just_saw_decl = 2;
  355.         ps.in_decl = true;
  356.         }
  357.         prefix_blankline_requested = 0;
  358.         parse(rbrace);    /* let parser know about this */
  359.         ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead && ps.il[ps.tos] >= ps.ind_level;
  360.         if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
  361.         postfix_blankline_requested = 1;
  362.         break;
  363.  
  364.     case swstmt:        /* got keyword "switch" */
  365.         sp_sw = true;
  366.         hd_type = swstmt;    /* keep this for when we have seen the
  367.                  * expression */
  368.         goto copy_id;    /* go move the token into buffer */
  369.  
  370.     case sp_paren:        /* token is if, while, for */
  371.         sp_sw = true;    /* the interesting stuff is done after the
  372.                  * expression is scanned */
  373.         hd_type = (*token == 'i' ? ifstmt :
  374.         (*token == 'w' ? whilestmt : forstmt));
  375.  
  376.         /* remember the type of header for later use by parser */
  377.         goto copy_id;    /* copy the token into line */
  378.  
  379.     case sp_nparen:    /* got else, do */
  380.         ps.in_stmt = false;
  381.         if (*token == 'e') {
  382.         if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
  383.             if (verbose)
  384.             diag(0, "Line broken");
  385.             dump_line();/* make sure this starts a line */
  386.             ps.want_blank = false;
  387.         }
  388.         force_nl = true;/* also, following stuff must go onto new
  389.                  * line */
  390.         last_else = 1;
  391.         parse(elselit);
  392.         } else {
  393.         if (e_code != s_code) {        /* make sure this starts a
  394.                          * line */
  395.             if (verbose)
  396.             diag(0, "Line broken");
  397.             dump_line();
  398.             ps.want_blank = false;
  399.         }
  400.         force_nl = true;/* also, following stuff must go onto new
  401.                  * line */
  402.         last_else = 0;
  403.         parse(dolit);
  404.         }
  405.         goto copy_id;    /* move the token into line */
  406.  
  407.     case decl:        /* we have a declaration type (int, register,
  408.                  * etc.) */
  409.         parse(decl);    /* let parser worry about indentation */
  410.         if (ps.last_token == rparen && ps.tos <= 1)
  411.         ps.in_parameter_declaration = 1;
  412.         if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
  413.         ps.ind_level = ps.i_l_follow = 1;
  414.         ps.ind_stmt = 0;
  415.         }
  416.         ps.in_or_st = true;    /* this might be a structure or
  417.                  * initialization declaration */
  418.         ps.in_decl = ps.decl_on_line = true;
  419.         if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
  420.         ps.just_saw_decl = 2;
  421.         prefix_blankline_requested = 0;
  422.         for (i = 0; token[i++];);    /* get length of token */
  423.  
  424.         /* dec_ind = e_code - s_code + (ps.decl_indent>i ? ps.decl_indent
  425.          * : i); */
  426.         dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
  427.         goto copy_id;
  428.  
  429.     case ident:        /* got an identifier or constant */
  430.         if (ps.in_decl) {    /* if we are in a declaration, we must indent
  431.                  * identifier */
  432.         if (ps.want_blank)
  433.             *e_code++ = ' ';
  434.         ps.want_blank = false;
  435.         if (is_procname == 0 || !procnames_start_line) {
  436.             if (!ps.block_init)
  437.             if (troff && !ps.dumped_decl_indent) {
  438.                 sprintf(e_code, "\\c\n.De %dp+\200p\n", dec_ind * 7);
  439.                 ps.dumped_decl_indent = 1;
  440.                 e_code += strlen(e_code);
  441.             } else
  442.                 while ((e_code - s_code) < dec_ind)
  443.                 *e_code++ = ' ';
  444.         } else {
  445.             if (dec_ind && s_code != e_code)
  446.             dump_line();
  447.             dec_ind = 0;
  448.             ps.want_blank = false;
  449.         }
  450.         } else if (sp_sw && ps.p_l_follow == 0) {
  451.         sp_sw = false;
  452.         force_nl = true;
  453.         ps.last_u_d = true;
  454.         ps.in_stmt = false;
  455.         parse(hd_type);
  456.         }
  457.     copy_id:
  458.         if (ps.want_blank)
  459.         *e_code++ = ' ';
  460.         if (troff && ps.its_a_keyword) {
  461.         *e_code++ = BACKSLASH;
  462.         *e_code++ = 'f';
  463.         *e_code++ = 'B';
  464.         }
  465.         for (t_ptr = token; *t_ptr; ++t_ptr)
  466.         *e_code++ = *t_ptr;
  467.         if (troff && ps.its_a_keyword) {
  468.         *e_code++ = BACKSLASH;
  469.         *e_code++ = 'f';
  470.         *e_code++ = 'R';
  471.         }
  472.         ps.want_blank = true;
  473.         break;
  474.  
  475.     case period:        /* treat a period kind of like a binary
  476.                  * operation */
  477.         *e_code++ = '.';    /* move the period into line */
  478.         ps.want_blank = false;    /* dont put a blank after a period */
  479.         break;
  480.  
  481.     case comma:
  482.         ps.want_blank = (s_code != e_code);        /* only put blank after
  483.                              * comma if comma does
  484.                              * not start the line */
  485.         if (ps.in_decl && is_procname == 0 && !ps.block_init)
  486.         while ((e_code - s_code) < (dec_ind - 1))
  487.             *e_code++ = ' ';
  488.  
  489.         *e_code++ = ',';
  490.         if (ps.p_l_follow == 0) {
  491.         ps.block_init = 0;
  492.         if (break_comma && !ps.leave_comma)
  493.             force_nl = true;
  494.         }
  495.         break;
  496.  
  497.     case preesc:        /* got the character '#' */
  498.         if ((s_com != e_com) || (s_lab != e_lab) || (s_code != e_code)) {
  499.         dump_line();
  500.         }
  501.         *e_lab++ = '#';    /* move whole line to 'label' buffer */
  502.  
  503.         /* a large section of code was removed here to break these files
  504.          * up into msc sized chunks */
  505.         dopreesc();
  506.  
  507.         if (strncmp(s_lab, "#if", 3) == 0) {
  508.         if (ifdef_level < sizeof state_stack / sizeof state_stack[0]) {
  509.             match_state[ifdef_level].tos = -1;
  510.             state_stack[ifdef_level++] = ps;
  511.         } else {
  512.             diag(1, "#if stack overflow");
  513.         }
  514.         } else if (strncmp(s_lab, "#else", 5) == 0) {
  515.         if (ifdef_level <= 0) {
  516.             diag(1, "Unmatched #else");
  517.         } else {
  518.             match_state[ifdef_level - 1] = ps;
  519.             ps = state_stack[ifdef_level - 1];
  520.         }
  521.         } else if (strncmp(s_lab, "#endif", 6) == 0) {
  522.         if (ifdef_level <= 0) {
  523.             diag(1, "Unmatched #endif");
  524.         } else {
  525.             ifdef_level--;
  526. #ifdef undef
  527.  
  528.             /* This match needs to be more intelligent before the
  529.              * message is useful */
  530.             if (match_state[ifdef_level].tos >= 0
  531.             && /* bcmp */ memcmp(&ps, &match_state[ifdef_level], sizeof ps))
  532.             diag(0, "Syntactically inconsistant #ifdef alternatives.");
  533. #endif
  534.         }
  535.         }
  536.         break;        /* subsequent processing of the newline
  537.                  * character will cause the line to be
  538.                  * printed */
  539.  
  540.     case comment:        /* we have gotten a /*  this is a biggie */
  541.     proc_comment:
  542.         if (flushed_nl) {    /* we should force a broken line here */
  543.         flushed_nl = false;
  544.         dump_line();
  545.         ps.want_blank = false;    /* dont insert blank at line start */
  546.         force_nl = false;
  547.         }
  548.         pr_comment();
  549.         break;
  550.     }                /* end of big switch stmt */
  551. }
  552.